package com.example.aspect;

import com.example.anno.CheckName;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.FieldSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

@Aspect
@Component
public class CheckNameAspect {

    @Pointcut("@annotation(com.example.anno.CheckSqlInjection)")
    public void pointcut() {

    }

//    @Before("pointcut()")
    public void beforeMethod(JoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();
        FieldSignature fieldSignature = (FieldSignature) joinPoint.getSignature();
        Object fieldValue = fieldSignature.getField().get(target);

        if (fieldValue instanceof String) {
            String fieldName = fieldSignature.getName();
            String modifiedValue = ((String) fieldValue).replace("test", "prod");
            fieldSignature.getField().set(target, modifiedValue);
            System.out.println("Modified value of field " + fieldName + ": " + modifiedValue);
        }
    }

    @Before("pointcut()")
    public void beforeMethod1(JoinPoint joinPoint) throws Throwable {
        Object target = joinPoint.getTarget();

        // 1. 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 2. 获取方法
        Method method = methodSignature.getMethod();
        // 3. 获取方法的所有参数
        Parameter[] parameters = method.getParameters();

        // 4. 遍历参数和其对应的注解
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            // 5. 检查参数是否被@CheckName注解
            boolean checkNameAnnotation = parameter.isAnnotationPresent(CheckName.class);
            if (!checkNameAnnotation) {
                continue;
            }
            // 6. 获取参数值
            Object argValue = joinPoint.getArgs()[i];
            // 7. 获取参数的字段
            Class<?> argClass = argValue.getClass();
            // 8. 获取参数的所有字段
            Field[] fields = argClass.getDeclaredFields();
            // 9. 对字段进行访问权限设置，以便读取注解信息（如果需要）
            for (Field field : fields) {
                field.setAccessible(true);
                CheckName checkName = field.getAnnotation(CheckName.class);
                if (checkName == null) {
                    continue;
                }

                // 11. 获取字段的值
                Object fieldValue = field.get(argValue);
                boolean checkOrder = checkName.checkOrder();
                if (checkOrder) {
                    if (!fieldValue.equals("desc") && !fieldValue.equals("asc")) {
                        throw new RuntimeException("order 参数错误!");
                    }
                    continue;
                }
                // 打印或处理带有@CheckName注解的字段
                System.out.println("Field with @CheckName: " + field.getName() + ", Value: " + fieldValue);

                // 12. 替换值
                field.set(argValue, String.valueOf(fieldValue).replace("test", "prod"));
            }
        }
    }

//    @Before("pointcut()")
    public void beforeMethod2(JoinPoint joinPoint) throws Throwable {
        // 1. 获取方法签名
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 2. 获取方法
        Method method = methodSignature.getMethod();
        // 3. 获取方法的所有参数
        Parameter[] parameters = method.getParameters();

        // 4. 遍历参数和其对应的注解
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            // 5. 检查参数是否被@CheckName注解
            CheckName checkNameAnnotation = parameter.getAnnotation(CheckName.class);
            if (checkNameAnnotation != null) {
                // 6. 获取参数值
                Object argValue = joinPoint.getArgs()[i];
                // 7. 获取参数的字段
                Class<?> argClass = argValue.getClass();
                // 8. 获取参数的所有字段
                Field[] fields = argClass.getDeclaredFields();
                // 9. 对字段进行访问权限设置，以便读取注解信息（如果需要）
                for (Field field : fields) {
                    field.setAccessible(true);
                    // 10. 检查字段是否被@CheckName注解
                    if (field.isAnnotationPresent(CheckName.class)) {
                        // 11. 获取字段的值
                        Object fieldValue = field.get(argValue);
                        // 打印或处理带有@CheckName注解的字段
                        System.out.println("Field with @CheckName: " + field.getName() + ", Value: " + fieldValue);

                        // 12. 替换值
                        field.set(argValue, String.valueOf(fieldValue).replace("test", "prod"));
                    }
                }
            }
        }
    }


}